package com.csw.android.player.view.video

import android.content.Context
import android.content.pm.ActivityInfo
import android.graphics.Color
import android.os.Build
import android.util.AttributeSet
import android.view.SurfaceView
import android.view.TextureView
import android.widget.FrameLayout
import android.widget.ImageView
import androidx.activity.ComponentActivity
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.Observer
import com.csw.android.player.PlayerManager
import com.csw.android.player.base.AbsMediaControllerView
import com.csw.android.player.base.IMediaPlayer
import com.csw.android.player.base.IPlayerHolder
import com.csw.android.player.base.IPlayerView
import com.csw.android.player.base.MediaInfo
import com.csw.android.player.base.OnControllerListener
import com.csw.android.player.base.PlayList
import com.csw.android.player.base.PlayerInfo
import com.csw.android.player.base.VideoRatio
import com.csw.android.player.ui.full.FullScreenPlayActivity
import com.csw.android.player.utils.ScreenOrientationUtils
import com.csw.android.player.view.controller.GestureView
import com.csw.android.player.view.controller.PreviewView
import com.csw.android.player.view.render.RenderView
import com.csw.android.player.view.window.SystemAlertWindowPermission
import com.csw.android.player.view.window.VideoFloatWindow
import com.google.android.material.snackbar.Snackbar

/**
 * 视频播放器视图
 */
open class VideoView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : FrameLayout(context, attrs), IPlayerView, DefaultLifecycleObserver {


    /** 播放器状态信息监听，更新渲染视图尺寸，根据播放状态维持屏幕常亮 */
    private val playInfoListener = Observer<Long?> {
        mMediaPlayer?.playerInfo?.run {
            mRenderView.updateVideoSize(videoWidth, videoHeight)
            keepScreenOn = buttonPlaying
        }
    }

    /** 当前绑定的播放器，其绑定与解绑由本类负责，子类不该修改 */
    protected var mMediaPlayer: IMediaPlayer? = null
        private set

    /** 渲染视图 */
    protected val mRenderView = RenderView(context)

    /** 手势处理视图 */
    protected val mGestureView = GestureView(context).apply {
        player = this@VideoView
        singleTapListener = {
            mMediaController?.run {
                showing = !showing
            }
        }
        doubleTapListener = {
            if (isPlaying()) {
                pause()
            } else {
                play()
            }
        }
        transformListener = {
            mRenderView.transformMatrix = it
        }
    }
    protected val mPreviewView = PreviewView(context)
    protected val mMediaController: AbsMediaControllerView?

    /**使用单例播放器*/
    val useSinglePlayer: Boolean = true

    init {
        setBackgroundColor(Color.BLACK)
        addView(mRenderView, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
        addView(
            mGestureView,
            LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
        )
        addView(
            mPreviewView,
            LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
        )
        mMediaController = createMediaController(context)
        mMediaController?.let {
            it.mMediaPlayer = this
            it.onControllerListener = object : OnControllerListener {
                override fun onScaleTypeChange(scaleType: ImageView.ScaleType) {
                    mRenderView.scaleType = scaleType
                }

                override fun onVideoRatioChange(videoRatio: VideoRatio) {
                    mRenderView.widthHeightRatio = videoRatio.whRatio
                }

                override fun onMirrorChange(mirror: Boolean) {
                    mRenderView.mirror = mirror
                }

                override fun enterFullScreen() {
                    playerInfo?.run {
                        if (videoHeight > videoWidth) {
                            startFullScreenPlay(ScreenOrientationUtils.UIGravity.BOTTOM)
                        } else {
                            startFullScreenPlay(ScreenOrientationUtils.UIGravity.LEFT)
                        }
                    }
                }

                override fun enterFloatWindow() {
                    tryPlayInWindow()
                }
            }
            addView(
                it,
                LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
            )
        }
        post {
            if (lifecycleOwner == null) {
                context.run {
                    if (this is ComponentActivity) {
                        lifecycleOwner = this
                    }
                }
            }
        }
    }

    //region protected function--------------------------------------------------------------------

    /**
     * 开始全屏播放
     *
     * @param uiGravity UI重力方向
     */
    protected open fun startFullScreenPlay(uiGravity: ScreenOrientationUtils.UIGravity) {
        FullScreenPlayActivity.open(
            context,
            playId,
            when (uiGravity) {
                ScreenOrientationUtils.UIGravity.BOTTOM -> ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
                ScreenOrientationUtils.UIGravity.TOP -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
                ScreenOrientationUtils.UIGravity.LEFT -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
                ScreenOrientationUtils.UIGravity.RIGHT -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
            }
        )
    }

    /**
     * 检查悬浮窗权限并在悬浮窗中播放
     */
    protected open fun tryPlayInWindow() {
        val activity = context
        if (activity is FragmentActivity) {
            SystemAlertWindowPermission.request(
                activity,
                object : SystemAlertWindowPermission.OnRequestResultListener {
                    override fun onResult(isGranted: Boolean) {
                        if (isGranted) {
                            playInWindow()
                        } else {
                            if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O) {
                                //Android 8.0存在一个bug，用户在设置页面开启悬浮窗权限并返回，此时并不能得到正确的悬浮窗权限结果，但实际已经可以添加悬浮窗
                                Snackbar.make(
                                    this@VideoView,
                                    "没有悬浮窗权限，Android 8.0手机第一次开启权限会提示失败，但实际已有权限，再次点击悬浮窗按钮即可",
                                    Snackbar.LENGTH_LONG
                                ).show()
                            } else {
                                Snackbar.make(
                                    this@VideoView,
                                    "没有悬浮窗权限",
                                    Snackbar.LENGTH_SHORT
                                ).show()
                            }
                        }
                    }
                })
        }
    }

    /**
     * 在悬浮窗中播放
     */
    private fun playInWindow() {
        mediaInfo?.let {
            VideoFloatWindow.instance.run {
                show()
                startPlay(playId)
            }
        }
    }

    protected open fun createMediaController(context: Context): AbsMediaControllerView? {
        return null
    }

    //endregion

    //region IPlayerView----------------------------------------------------------------------------------

    override var lifecycleOwner: LifecycleOwner? = null
        set(value) {
            if (field == value) {
                return
            }
            field?.lifecycle?.removeObserver(this)
            field = value
            field?.lifecycle?.addObserver(this)
        }
    override var isMediaControllerShowing: Boolean
        get() = mMediaController?.showing == true
        set(value) {
            mMediaController?.showing = value
        }

    //endregion

    //region IMediaPlayer---------------------------------------------------------------------------

    override val playId: String
        get() {
            return ensurePlayer().playId
        }

    private fun ensurePlayer(): IMediaPlayer {
        val mp = mMediaPlayer
        if (mp != null) {
            return mp
        } else {
            return if (useSinglePlayer) {
                PlayerManager.SINGLE_PLAYER
            } else {
                PlayerManager.newPlayer()
            }.apply {
                playerHolder = this@VideoView
            }
        }
    }

    override val playList: PlayList?
        get() = mMediaPlayer?.playList

    override val playerInfo: PlayerInfo?
        get() = mMediaPlayer?.playerInfo

    override var playerHolder: IPlayerHolder?
        get() = mMediaPlayer?.playerHolder
        set(value) {
            mMediaPlayer?.playerHolder = value
        }

    override var mediaInfo: MediaInfo? = null
        set(value) {
            if (field == value) {
                return
            }
            field = value
            mPreviewView.loadPreviewImage(field?.coverUri?.toString())
            mMediaPlayer?.mediaInfo = field
        }

    override fun play() {
        //开始播放时，检查是否已经绑定播放器，没有则进行绑定
        ensurePlayer()
        mMediaPlayer?.let { pm ->
            //更新一下播放信息
            pm.mediaInfo = mediaInfo
            pm.play()
        }
    }

    override fun pause() {
        mMediaPlayer?.pause()
    }

    override fun reset() {
        mMediaPlayer?.reset()
    }

    override fun release() {
        mMediaPlayer?.release()
    }

    override fun isPlaying(): Boolean {
        return mMediaPlayer?.isPlaying() == true
    }

    override fun getContentDuration(): Long {
        return mMediaPlayer?.getContentDuration() ?: 0L
    }

    override fun getContentProgress(): Long {
        return mMediaPlayer?.getContentProgress() ?: 0L
    }

    override fun setContentProgress(progress: Long) {
        mMediaPlayer?.setContentProgress(progress)
    }

    override fun setSurfaceView(surfaceView: SurfaceView?) {
        mMediaPlayer?.setSurfaceView(surfaceView)
    }

    override fun setTextureView(textureView: TextureView?) {
        mMediaPlayer?.setTextureView(textureView)
    }

    //endregion

    //region IPlayerHolder--------------------------------------------------------------------------
    override fun onPlayerBind(mediaPlayer: IMediaPlayer) {
        this.mMediaPlayer = mediaPlayer
        mRenderView.settingPlayerSurface(this, true)
        mMediaController?.registerPlayerListener()
        mediaPlayer.playerInfo?.onInfoUpdate?.observeForever(playInfoListener)
        if (mPreviewView.isShowing()) {
            mPreviewView.hide()
        }
    }

    override fun onPlayerUnbind(mediaPlayer: IMediaPlayer) {
        if (!mPreviewView.isShowing()) {
            mPreviewView.show()
        }
        mMediaController?.unregisterPlayerListener()
        mRenderView.settingPlayerSurface(this, false)
        mediaPlayer.playerInfo?.onInfoUpdate?.removeObserver(playInfoListener)
        this.mMediaPlayer = null
    }

    //endregion-------------------------------------------------------------------------------------

    //region lifecycle------------------------------------------------------------------------------

    /** 页面恢复时，若当前媒体不为空且标记使用单例播放器，则将播放器绑定到此视图 */
    override fun onResume(owner: LifecycleOwner) {
        super.onResume(owner)
        if (mediaInfo != null
            && mMediaPlayer == null
            && useSinglePlayer
            && !VideoFloatWindow.instance.isShowing()
        ) {
            if (PlayerManager.SINGLE_PLAYER.mediaInfo == mediaInfo) {
                PlayerManager.SINGLE_PLAYER.playerHolder = this
            }
        }
    }

    /** 页面销毁时，释放当前绑定的播放器 */
    override fun onDestroy(owner: LifecycleOwner) {
        super.onDestroy(owner)
        mMediaPlayer?.release()
        mMediaPlayer?.playerHolder = null
    }

    //endregion
}